home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Vertigo / RenderEngine / FlushPort.c < prev    next >
C/C++ Source or Header  |  2000-06-23  |  10KB  |  375 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //    File:        FlushPort.c
  4. //
  5. //    Project:    MacHack 2000 - Vertigo!
  6. //    Authors:    Darrin Cardani, Drew Thaler, Ed Wynne
  7. //
  8. //    Date:        06/23/2000 (written entirely during the conference!)
  9. //
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. #include <alloca.h>
  13. #include <DriverServices.h>
  14. #include <Types.h>
  15. #include <Memory.h>
  16. #include <Quickdraw.h>
  17. #include <QDOffscreen.h>
  18. #include <Fonts.h>
  19. #include <Events.h>
  20. #include <Menus.h>
  21. #include <Windows.h>
  22. #include <TextEdit.h>
  23. #include <Dialogs.h>
  24. #include <OSUtils.h>
  25. #include <Sound.h>
  26. #include <string.h>
  27. #include <ToolUtils.h>
  28.  
  29. #include "DebugUtils.h"
  30. #include "DrawingUtils.h"
  31. #include "DrawingFunctions.h"
  32. #include "FlushPort.h"
  33.  
  34. // • Prototypes
  35. void main(void);
  36. void InitializeToolbox(void);
  37.  
  38.  
  39. // ----------------------------------------------------------------------------------
  40. //    main
  41. // ----------------------------------------------------------------------------------
  42.  
  43. /*
  44. void main(void)
  45. {
  46.     // Set up the mac application.
  47.     InitializeToolbox();
  48.     
  49.     // Create a couple of empty windows for show.
  50.     Rect        windowRects[] = { {300,450,600,800}, {100,100,450,600}, {240,444,464,989}, {256,196,645,732} };
  51.     int            numWindows = sizeof(windowRects) / sizeof(Rect);
  52.     WindowPtr    *windowList = (WindowPtr*)alloca(sizeof(WindowPtr)*numWindows);
  53.     RegionList    windowRegions;
  54.     
  55.     for (int i=0; i<numWindows; ++i)
  56.     {
  57.         windowList[i] = NewCWindow(NULL,&windowRects[i],"\pWindow",true,documentProc,(WindowPtr)-1L,false,0);
  58.         windowRegions.Add(((WindowPeek)windowList[i])->strucRgn,true);
  59.     }
  60.     
  61.     // Fetch the color window manager port.
  62.     CGrafPtr    wmgrPort;
  63.     GetCWMgrPort(&wmgrPort);
  64.     
  65.     // Allocate a whole mess of GWorlds.  Error checking is for pussies.
  66.     StGWorld    screenGWorld(wmgrPort);
  67.     StGWorld    dropShadowWorld(wmgrPort);
  68.     StGWorld    preShiftWorld(wmgrPort);
  69.     StGWorld    scratchWorld(wmgrPort);
  70.     StGWorld    postShiftWorld(wmgrPort);
  71.     
  72.     // Grab an image of the current screen.
  73.     CopyPortToGWorld(wmgrPort,screenGWorld);
  74.     
  75.     // Create a window the same size as the screen, and display it.  This doesn't
  76.     //    get us above floaters (like the stupid control strip), but it's fine for a test app.
  77.     StHideMenuBar    hideMenuBar;
  78.     WindowPtr    screenWindow = NewCWindow(NULL,&wmgrPort->portRect,"\pdrew's screen display",true,plainDBox,(WindowPtr)-1L,false,0);
  79.     
  80.     // Create a composite GWord for the output.  Alternatively, composite onscreen for debugg.
  81.     //StGWorld    compositeWorld(wmgrPort);
  82.     GWorldPtr    compositeWorld = (CGrafPtr)screenWindow;
  83.     
  84.     {
  85.         // For debugging, erase the composite world to black.
  86.         {
  87.             StSetGWorld    setPort(compositeWorld);
  88.             BackColor(blackColor);
  89.             EraseRect(&((CGrafPtr)compositeWorld)->portRect);
  90.         }
  91.         
  92.         // Time to doctor the screenshot with our code.  For the test app,
  93.         //    we do the whole damn thing at once.
  94.         StRegion    maskRegion(*screenGWorld.PortRect());
  95.         
  96.         // Lay down some drop shadows.
  97.         RenderDropShadows(screenGWorld,dropShadowWorld,maskRegion,windowRegions);
  98.         
  99.         // Loop across each window to do the red-shifting.
  100.         const float    maxDepth = 10;
  101.         for (int i=-1; i<numWindows; ++i)
  102.         {
  103.             int            windowIndex = numWindows - i;
  104.             float        depthToUse = maxDepth - (maxDepth / windowIndex);
  105.             int            inPlane = (windowIndex == 1);
  106.             StRegion    rgn;
  107.             
  108.             // Figure out which region we're starting with.
  109.             if (i == -1)
  110.             {
  111.                 rgn = wmgrPort->portRect;
  112.                 depthToUse = 10;
  113.             }
  114.             else
  115.             {
  116.                 rgn = windowRegions[i];
  117.             }
  118.             
  119.             // Subtract out all windows above it, and clip to our mask.
  120.             for (int j=i+1; j<numWindows; ++j)
  121.                 rgn -= windowRegions[j];
  122.             rgn &= maskRegion;
  123.             
  124.             // Skip if we've eliminated everything.
  125.             if (rgn.IsEmpty()) continue;
  126.             
  127.             // Red shift if it's not in the plane... otherwise just copy it wholesale.
  128.             if (!inPlane)
  129.             {
  130.                 CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
  131.                 RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
  132.                 CopyIntoComposite(postShiftWorld,compositeWorld,rgn);
  133.             }
  134.             else
  135.             {
  136.                 CopyIntoComposite(dropShadowWorld,compositeWorld,rgn);
  137.             }
  138.             
  139.             // Blit our composited image back into visible space.
  140.             CopyGWorldToPort(compositeWorld,screenWindow,maskRegion);
  141.             
  142.             // Wait for a mousedown.  We WNE so drew can grab a screen shot.
  143.             while (!Button()) { EventRecord ev; WaitNextEvent(everyEvent,&ev,0,NULL); SystemTask(); }
  144.             while (Button()) {}
  145.         }
  146.     }
  147.     
  148.     // Hang out for a while.
  149.     
  150.     for (int i=0; i<numWindows; ++i)
  151.         DisposeWindow(windowList[i]);
  152.     DisposeWindow(screenWindow);
  153. }
  154.  
  155.  
  156. // ----------------------------------------------------------------------------------
  157. //    InitializeToolbox
  158. // ----------------------------------------------------------------------------------
  159. void InitializeToolbox(void)
  160. {
  161.     OSErr        err;
  162.     SysEnvRec    theWorld;
  163.         
  164.     //    Test the computer to be sure we can do color.  
  165.     //    If not we would crash, which would be bad.  
  166.     //    If we can’t run, just beep and exit.
  167.     //     (•• can you tell this code was descended from SillyBalls? ••)
  168.     err = SysEnvirons(1, &theWorld);
  169.     if (theWorld.hasColorQD == false) {
  170.         SysBeep(50);
  171.         ExitToShell();
  172.     }
  173.     
  174.     // Initialize all the needed managers.
  175.     InitGraf(&qd.thePort);
  176.     InitFonts();
  177.     InitWindows();
  178.     InitMenus();
  179.     TEInit();
  180.     InitDialogs(nil);
  181.     InitCursor();
  182.     
  183.     GetDateTime((unsigned long*) &qd.randSeed);
  184.     if ((UInt32)UpTime != 0)
  185.         qd.randSeed ^= UpTime().lo;
  186. }
  187.  
  188. */
  189.  
  190.  
  191. // -- When passed a zero-based index, this function passes back the indicated
  192. // -- menu's rect (0=top-most, n-1=bottom-most). Returns false if no more menus.
  193.  
  194. #define kMBSaveLoc        0x0B5C
  195. #define kLengthCookie    0x001C
  196.  
  197. Boolean MenuSnitch(short menuIndex, Rect *menuRect);
  198. Boolean MenuSnitch(short menuIndex, Rect *menuRect)
  199. {
  200. Boolean    result = false;
  201. short    menuCount = 0;
  202. Handle    mbSaveLoc = * (Handle *) kMBSaveLoc;
  203.  
  204. if (mbSaveLoc)
  205.     menuCount = (** (short **) mbSaveLoc) / kLengthCookie;
  206.  
  207. if ((menuIndex >= 0) && (menuIndex < menuCount))
  208.     {
  209.     (*menuRect) = * (Rect *) (*mbSaveLoc +((menuIndex + 1) * kLengthCookie));
  210.     result = true;
  211.     }
  212.  
  213. return(result);
  214. }    // -- MenuSnitch
  215.  
  216.  
  217. extern GWorldPtr    dropShadowWorld;
  218. extern GWorldPtr    preShiftWorld;
  219. extern GWorldPtr    scratchWorld;
  220. extern GWorldPtr    postShiftWorld;
  221. extern GWorldPtr    gStageBuffer;
  222.  
  223.  
  224. void RenderBufferOntoScreen(GWorldPtr srcWorld,GWorldPtr dstWorld,Rect *inRect,RgnHandle inMask)
  225. {
  226.     THz    oldZone = GetZone();
  227.     SetZone(SystemZone());
  228.     
  229.     StRegion    fullScreen(dstWorld->portRect);
  230.     
  231.     // Build a list of the window regions, in back-to-front order.  We don't
  232.     //    include the desktop in this list.
  233.     RegionList    windowRegions;
  234.     bool        windowListChanged = false;
  235.     BuildWindowList(windowRegions,windowListChanged);
  236.     
  237.     if (windowListChanged)
  238.     {
  239.         // Re-blit the entire screen.
  240.         *inRect = dstWorld->portRect;
  241.         CopyRgn(fullScreen,inMask);
  242.     }
  243.     
  244.     // Lay down some fresh drop shadows.
  245.     RenderDropShadows(srcWorld,dropShadowWorld,inMask,windowRegions);
  246.     
  247.     // Loop across each window to do the red-shifting.
  248.     const float    maxDepth = 10;
  249.     int            numWindows = windowRegions.GetCount();
  250.     for (int i=-1; i<numWindows; ++i)
  251.     {
  252.         int            windowIndex = numWindows - i;
  253.         int            depthToUse = maxDepth - (maxDepth / windowIndex);
  254.         int            inPlane = (windowIndex <= 2);
  255.         StRegion    rgn;
  256.         
  257.         // Figure out which region we're starting with.
  258.         if (i == -1)
  259.         {
  260.             rgn = dstWorld->portRect;
  261.             depthToUse = 10;
  262.         }
  263.         else
  264.         {
  265.             rgn = windowRegions[i];
  266.         }
  267.         
  268.         // Subtract out all windows above it, and clip to our mask.
  269.         for (int j=i+1; j<numWindows; ++j)
  270.             rgn -= windowRegions[j];
  271.         rgn &= inMask;
  272.         
  273.         // Skip if we've eliminated everything.
  274.         if (rgn.IsEmpty()) continue;
  275.         
  276.         // Red shift if it's not in the plane... otherwise just copy it wholesale.
  277.         if (!inPlane)
  278.         {
  279.             CopyRegionForRedShifting(dropShadowWorld,preShiftWorld,rgn);
  280.             RedShiftAndBlur(preShiftWorld,scratchWorld,postShiftWorld,rgn,depthToUse);
  281.             CopyIntoComposite(postShiftWorld,gStageBuffer,rgn);
  282.         }
  283.         else
  284.         {
  285.             CopyIntoComposite(dropShadowWorld,gStageBuffer,rgn);
  286.         }
  287.     }
  288.     
  289.     if (numWindows > 0)
  290.         DisposeRgn(windowRegions[numWindows-1]);
  291.     
  292.     CopyGWorldToGWorld(gStageBuffer,dstWorld);
  293.     SetZone(oldZone);
  294. }
  295.  
  296.  
  297. // --------------------------------------------------------
  298. // Single-app window list
  299. void
  300. BuildWindowList(RegionList &windowList, bool &windowListChanged)
  301. {
  302.     static UInt32    oldList[1024] = {0};
  303.     static UInt32    newList[1024] = {0};
  304.     UInt32            *newListCursor = &newList[0];
  305.     UInt32            remaining = 1024;
  306.     ProcessSerialNumber    currentProcess = { 0, kCurrentProcess };
  307.     ProcessSerialNumber thisProcess = {0,0};
  308.     Boolean                same = false;
  309.     
  310.     // For now we only do the front app's windows.  Yeah this is lame and sucks, but it'll
  311.     //    make us work for now.
  312.     GetCurrentProcess(&thisProcess);
  313.     if ((SameProcess(&thisProcess,¤tProcess,&same) != noErr) || !same)
  314.     {
  315.         windowListChanged = false;
  316.         return;
  317.     }
  318.     
  319.     // Since it's close to demo time...
  320.     windowListChanged = true;
  321.     
  322.     // Grab the menu bar and the active menus.
  323.     {
  324.         StRegion    rgn;
  325.         GDHandle    mainDevice = GetMainDevice();
  326.         
  327.         SetRectRgn(rgn,mainDevice[0]->gdRect.left,mainDevice[0]->gdRect.top,mainDevice[0]->gdRect.right,mainDevice[0]->gdRect.top+GetMBarHeight());
  328.         
  329.         // Add the current menu region here.
  330.         Rect    menuRect;
  331.         short    index = 0;
  332.         while (MenuSnitch(index++,&menuRect))
  333.             rgn += menuRect;
  334.         
  335.         windowList.Add(rgn,true);
  336.     }
  337.     
  338.     // Grab the visible windows in front-to-back order.
  339.     WindowPeek    window = (*(WindowPeek*)0x9D6);
  340.     while ((window != NULL) && (window != (WindowPeek)-1L))
  341.     {
  342.         if (window->visible)
  343.         {
  344.             windowList.Add(window->strucRgn,false);
  345.             
  346.             *(newListCursor++) = (UInt32)window;
  347.             *(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.top;
  348.             *(newListCursor++) = *(UInt32*)&window->strucRgn[0]->rgnBBox.bottom;
  349.             remaining -= 3;
  350.             
  351.             dprintf(kDConPrefix "Registering window %08X %08X %08X\n", *(newListCursor-3), *(newListCursor-2), *(newListCursor-1));
  352.         }
  353.         
  354.         window = window->nextWindow;
  355.     }
  356.     
  357.     // See if the window ordering or locations has changed since our last blit.
  358.     BlockZero(newListCursor,remaining*4);
  359.     if (!memcmp(oldList,newList,1024*4))
  360.     {
  361.         windowListChanged = true;
  362.         BlockMoveData(newList,oldList,1024*4);
  363.     }
  364.     
  365.     // Swap the windows in the list so that they're back-to-front.
  366.     int    count = windowList.GetCount();
  367.     for (int i=0; i<count/2; ++i)
  368.     {
  369.         RgnHandle    temp = windowList[i];
  370.         windowList[count-i-1] = windowList[i];
  371.         windowList[count-i-1] = temp;
  372.     }
  373. }
  374.  
  375.